#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "freertos/queue.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "cJSON.h"

#include "esp_http_client.h"
#include "esp_tls.h"
#include "esp_crt_bundle.h"
#include "esp_http_server.h"

// 项目Wi-Fi配置
#define WIFI_SSID "nn"
#define WIFI_PASS "00112233"

// 千问API配置 - 使用正确的端点和模型
#define QIANWEN_URL "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions"

#define API_KEY "sk-f954de51de78401684df0e895b15e567"

static const char *TAG = "QIANWEN_HTTP_SERVER";

// 事件组用于跟踪Wi-Fi连接状态
static EventGroupHandle_t wifi_event_group;
const int WIFI_CONNECTED_BIT = BIT0;

// 全局变量
char response_buffer[4096];
size_t response_len = 0;
char ai_response[2048] = {0};  // 存储AI的回复

// URL解码函数
void url_decode(char *str) {
    unsigned int i;
    char tmp[3] = {0};
    char *p = str;
    
    for (i = 0; i < strlen(str); i++) {
        if (str[i] == '%' && i + 2 < strlen(str)) {
            tmp[0] = str[i+1];
            tmp[1] = str[i+2];
            *p++ = (char)strtol(tmp, NULL, 16);
            i += 2;
        } else if (str[i] == '+') {
            *p++ = ' ';
        } else {
            *p++ = str[i];
        }
    }
    *p = '\0';
}

// HTTP事件处理程序
esp_err_t http_event_handler(esp_http_client_event_t *evt) {
    switch (evt->event_id) {
        case HTTP_EVENT_ON_DATA:
            ESP_LOGI(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
            if (!esp_http_client_is_chunked_response(evt->client)) {
                if (response_len + evt->data_len < sizeof(response_buffer)) {
                    memcpy(response_buffer + response_len, evt->data, evt->data_len);
                    response_len += evt->data_len;
                } else {
                    ESP_LOGE(TAG, "响应缓冲区溢出");
                }
            }
            break;
        case HTTP_EVENT_ON_FINISH:
            ESP_LOGI(TAG, "HTTP_EVENT_ON_FINISH");
            if (response_len > 0) {
                response_buffer[response_len] = '\0';
                ESP_LOGI(TAG, "完整响应: %s", response_buffer);
                
                // 解析千问API响应 
                cJSON *root = cJSON_Parse(response_buffer);
                if (root == NULL) {
                    ESP_LOGE(TAG, "JSON解析失败");
                    strcpy(ai_response, "解析API响应失败");
                    break;
                }
                
                // 检查错误
                cJSON *code = cJSON_GetObjectItem(root, "code");
                if (code != NULL && !cJSON_IsNull(code)) {
                    cJSON *message = cJSON_GetObjectItem(root, "message");
                    if (message != NULL && cJSON_IsString(message)) {
                        ESP_LOGE(TAG, "API错误: %s", message->valuestring);
                        snprintf(ai_response, sizeof(ai_response), "API错误: %s", message->valuestring);
                    }
                } else {
                    // 解析成功响应 
                    cJSON *choices = cJSON_GetObjectItem(root, "choices");
                    if (choices != NULL && cJSON_IsArray(choices)) {
                        cJSON *first_choice = cJSON_GetArrayItem(choices, 0);
                        if (first_choice != NULL) {
                            cJSON *message = cJSON_GetObjectItem(first_choice, "message");
                            if (message != NULL) {
                                cJSON *content = cJSON_GetObjectItem(message, "content");
                                if (content != NULL && cJSON_IsString(content)) {
                                    ESP_LOGI(TAG, "AI响应: %s", content->valuestring);
                                    // 存储AI回复，不直接打印到串口
                                    strncpy(ai_response, content->valuestring, sizeof(ai_response) - 1);
                                    ai_response[sizeof(ai_response) - 1] = '\0';
                                } else {
                                    strcpy(ai_response, "响应中未找到content字段");
                                }
                            } else {
                                strcpy(ai_response, "响应中未找到message字段");
                            }
                        } else {
                            strcpy(ai_response, "响应中未找到有效选项");
                        }
                    } else {
                        // 尝试其他可能的响应格式
                        cJSON *output = cJSON_GetObjectItem(root, "output");
                        if (output != NULL) {
                            cJSON *text = cJSON_GetObjectItem(output, "text");
                            if (text != NULL && cJSON_IsString(text)) {
                                ESP_LOGI(TAG, "AI响应: %s", text->valuestring);
                                strncpy(ai_response, text->valuestring, sizeof(ai_response) - 1);
                                ai_response[sizeof(ai_response) - 1] = '\0';
                            } else {
                                strcpy(ai_response, "未收到有效响应");
                            }
                        } else {
                            strcpy(ai_response, "未收到有效响应");
                        }
                    }
                }
                
                cJSON_Delete(root);
            }
            response_len = 0;
            break;
        case HTTP_EVENT_ERROR:
            ESP_LOGI(TAG, "HTTP_EVENT_ERROR");
            strcpy(ai_response, "HTTP请求错误");
            response_len = 0;
            break;
        default:
            break;
    }
    return ESP_OK;
}

// 发送请求到通义千问（OpenAI-Compatible）
void send_request_to_qianwen(const char *user_input)
{
    response_len = 0;                         // 全局响应长度清零
    memset(response_buffer, 0, sizeof(response_buffer));
    memset(ai_response, 0, sizeof(ai_response)); // 清空之前的回复

    /* 1. 构造 Chat-Completions 格式 JSON **************************/
    cJSON *root = cJSON_CreateObject();
    cJSON_AddStringToObject(root, "model", "qwen-turbo"); // 模型名称

    cJSON *messages = cJSON_CreateArray();
    cJSON *msg = cJSON_CreateObject();
    cJSON_AddStringToObject(msg, "role", "user");
    cJSON_AddStringToObject(msg, "content", user_input);
    cJSON_AddItemToArray(messages, msg);
    cJSON_AddItemToObject(root, "messages", messages);

    cJSON_AddNumberToObject(root, "temperature", 0.8);
    cJSON_AddNumberToObject(root, "top_p", 0.8);

    char *request_body = cJSON_PrintUnformatted(root);
    ESP_LOGI(TAG, "Request: %s", request_body);

    /* 2. HTTP 客户端配置 ******************************************/
    esp_http_client_config_t config = {
        .url = QIANWEN_URL,
        .event_handler = http_event_handler,
        .method = HTTP_METHOD_POST,
        .cert_pem = NULL,
        .crt_bundle_attach = esp_crt_bundle_attach,
        .timeout_ms = 15000,
        .buffer_size = 4096, 
    };

    esp_http_client_handle_t client = esp_http_client_init(&config);

    /* 3. 请求头 ****************************************************/
    esp_http_client_set_header(client, "Content-Type", "application/json");
    char auth[128];
    snprintf(auth, sizeof(auth), "Bearer %s", API_KEY);
    esp_http_client_set_header(client, "Authorization", auth);

    /* 4. 发送请求 *************************************************/
    esp_http_client_set_post_field(client, request_body, strlen(request_body));
    esp_err_t err = esp_http_client_perform(client);

    /* 5. 结果处理 *************************************************/
    if (err == ESP_OK) {
        int status = esp_http_client_get_status_code(client);
        ESP_LOGI(TAG, "HTTP Status = %d", status);
        if (status != 200) {
            ESP_LOGE(TAG, "HTTP error %d", status);
            snprintf(ai_response, sizeof(ai_response), "HTTP错误: %d", status);
        }
    } else {
        ESP_LOGE(TAG, "HTTP perform failed: %s", esp_err_to_name(err));
        snprintf(ai_response, sizeof(ai_response), "HTTP请求失败: %s", esp_err_to_name(err));
    }

    /* 6. 清理 ******************************************************/
    esp_http_client_cleanup(client);
    cJSON_Delete(root);
    free(request_body);
}

// WiFi事件处理函数
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
                              int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT) {
        if (event_id == WIFI_EVENT_STA_START) {
            esp_wifi_connect();
            ESP_LOGI(TAG, "开始连接WiFi...");
        } else if (event_id == WIFI_EVENT_STA_DISCONNECTED) {
            esp_wifi_connect();
            ESP_LOGI(TAG, "尝试重新连接...");
        }
    } else if (event_base == IP_EVENT) {
        if (event_id == IP_EVENT_STA_GOT_IP) {
            xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT);
            ESP_LOGI(TAG, "成功连接到WiFi!");
        }
    }
}

// WiFi初始化函数
void wifi_init(void)
{
    wifi_event_group = xEventGroupCreate();
    // 0.初始化NVS（非易失存储）- 用于保存WiFi配置等
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    // 1. 初始化网络接口  
    esp_netif_init();
    
    // 2. 创建默认事件循环
    esp_event_loop_create_default();
    
    // 3. 创建默认WiFi Station接口
    esp_netif_create_default_wifi_sta();

    // 4. 初始化WiFi配置
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&cfg);

    // 5. 注册WiFi事件处理器
    esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, NULL);
    esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL, NULL);

    // 6. 配置WiFi连接参数
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = WIFI_SSID,
            .password = WIFI_PASS,
        },
    };
    
    // 7. 设置WiFi为Station模式并应用配置
    esp_wifi_set_mode(WIFI_MODE_STA);
    esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
    
    // 8. 启动WiFi
    esp_wifi_start();
    
    ESP_LOGI(TAG, "WiFi初始化完成");
    // 9. 等待连接成功
    xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_BIT, pdFALSE, pdTRUE, portMAX_DELAY);
    ESP_LOGI(TAG, "已连接Wi-Fi并获取IP地址"); 
}

// HTTP请求处理函数 - 处理GET请求（提供网页表单）
static esp_err_t root_get_handler(httpd_req_t *req)
{
    // 简单的HTML表单
    const char *html_form = 
        "<!DOCTYPE html>"
        "<html>"
        "<head>"
        "<meta charset='UTF-8'>"
        "<title>ESP32 AI助手</title>"
        "<style>"
        "body { font-family: Arial, sans-serif; margin: 40px; }"
        "h1 { color: #333; }"
        "form { margin-top: 20px; }"
        "input[type=text] { width: 300px; padding: 10px; }"
        "input[type=submit] { padding: 10px 20px; background: #007bff; color: white; border: none; cursor: pointer; }"
        ".response { margin-top: 20px; padding: 15px; background: #f8f9fa; border-left: 4px solid #007bff; }"
        "</style>"
        "</head>"
        "<body>"
        "<h1>ESP32 AI助手</h1>"
        "<form method='post'>"
        "<input type='text' name='question' placeholder='请输入您的问题' required>"
        "<input type='submit' value='提问'>"
        "</form>";
    
    // 发送HTML响应
    httpd_resp_set_type(req, "text/html");
    httpd_resp_send(req, html_form, HTTPD_RESP_USE_STRLEN);
    
    return ESP_OK;
}

// HTTP请求处理函数 - 处理POST请求（接收问题并返回AI回复）
static esp_err_t root_post_handler(httpd_req_t *req)
{
    char content[256];
    char question[128] = {0};
    char decoded_question[128] = {0};
    
    // 获取POST数据内容
    int ret = httpd_req_recv(req, content, sizeof(content));
    if (ret <= 0) {
        if (ret == HTTPD_SOCK_ERR_TIMEOUT) {
            httpd_resp_send_408(req);
        }
        return ESP_FAIL;
    }
    content[ret] = '\0';
    
    // 解析表单数据，提取问题
    if (httpd_query_key_value(content, "question", question, sizeof(question)) == ESP_OK) {
        // URL解码
        strncpy(decoded_question, question, sizeof(decoded_question) - 1);
        url_decode(decoded_question);
        
        ESP_LOGI(TAG, "收到问题: %s", decoded_question);
        
        // 调用千问API
        send_request_to_qianwen(decoded_question);
        
        // 构建响应HTML
        char response_html[4000];
        snprintf(response_html, sizeof(response_html),
            "<!DOCTYPE html>"
            "<html>"
            "<head>"
            "<meta charset='UTF-8'>"
            "<title>ESP32 AI助手</title>"
            "<style>"
            "body { font-family: Arial, sans-serif; margin: 40px; }"
            "h1 { color: #333; }"
            "form { margin-top: 20px; }"
            "input[type=text] { width: 300px; padding: 10px; }"
            "input[type=submit] { padding: 10px 20px; background: #007bff; color: white; border: none; cursor: pointer; }"
            ".response { margin-top: 20px; padding: 15px; background: #f8f9fa; border-left: 4px solid #007bff; white-space: pre-wrap; }"
            "</style>"
            "</head>"
            "<body>"
            "<h1>ESP32 AI助手</h1>"
            "<form method='post'>"
            "<input type='text' name='question' placeholder='请输入您的问题' required>"
            "<input type='submit' value='提问'>"
            "</form>"
            "<div class='response'><strong>您的问题:</strong> %s<br><br><strong>AI回复:</strong> %s</div>"
            "</body>"
            "</html>",
            decoded_question, ai_response);
        
        // 发送响应
        httpd_resp_set_type(req, "text/html");
        httpd_resp_send(req, response_html, HTTPD_RESP_USE_STRLEN);
    } else {
        httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "无效的表单数据");
        return ESP_FAIL;
    }
    
    return ESP_OK;
}

// HTTP服务器URI配置
static const httpd_uri_t root = {
    .uri       = "/",
    .method    = HTTP_GET,
    .handler   = root_get_handler,
    .user_ctx  = NULL
};

static const httpd_uri_t root_post = {
    .uri       = "/",
    .method    = HTTP_POST,
    .handler   = root_post_handler,
    .user_ctx  = NULL
};

// 启动HTTP服务器
void start_webserver(void)
{
    httpd_handle_t server = NULL;
    httpd_config_t config = HTTPD_DEFAULT_CONFIG();
    config.stack_size = 10240; // 增加栈大小
    
    // 启动HTTP服务器
    if (httpd_start(&server, &config) == ESP_OK) {
        // 注册URI处理程序
        httpd_register_uri_handler(server, &root);
        httpd_register_uri_handler(server, &root_post);
        ESP_LOGI(TAG, "HTTP服务器启动成功");
    } else {
        ESP_LOGE(TAG, "HTTP服务器启动失败");
    }
}

// 主应用程序
void app_main(void)
{
    // 初始化WiFi
    wifi_init();
    
    // 启动HTTP服务器
    start_webserver();
    
    // 获取IP地址并打印
    esp_netif_ip_info_t ip_info;
    esp_netif_t *netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF");
    if (netif && esp_netif_get_ip_info(netif, &ip_info) == ESP_OK) {
        ESP_LOGI(TAG, "HTTP服务器已启动");
        ESP_LOGI(TAG, "请在浏览器中访问: http://" IPSTR, IP2STR(&ip_info.ip));
    }
    
    // 主循环保持运行
    while (1) {
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}